///////////////////////////////////////////////////////////////////////
// WriteEngine2Event.cpp
//
// Wrapper for DWriteEngine2Events Interface Events
//
// Written by Nic Wilson
//

#include "stdafx.h"
#include "WriteEngine2Event.h"

#include "WriteEngine2.h"

// CWriteEngine2Event

IMPLEMENT_DYNAMIC(CWriteEngine2Event, CCmdTarget)

BEGIN_INTERFACE_MAP(CWriteEngine2Event, CCmdTarget)
	INTERFACE_PART(CWriteEngine2Event, IID_IDispatch, WriteEngine2Events)
	INTERFACE_PART(CWriteEngine2Event, IID_DWriteEngine2Events, WriteEngine2Events)
END_INTERFACE_MAP()

CWriteEngine2Event::CWriteEngine2Event()
: m_hNotifyWnd(NULL)
, m_ptinfo(NULL)
, m_dwCookie(0)
, m_pUnkSink(0)
, m_pUnkSrc(0)
{
}

CWriteEngine2Event::~CWriteEngine2Event()
{
	if (m_dwCookie && (m_pUnkSrc != NULL) && (m_pUnkSink != NULL))
	{
		AfxConnectionUnadvise(m_pUnkSrc, IID_DWriteEngine2Events, m_pUnkSink, TRUE, m_dwCookie);
	}
}


BEGIN_MESSAGE_MAP(CWriteEngine2Event, CCmdTarget)
END_MESSAGE_MAP()



// CWriteEngine2Event message handlers

ULONG FAR EXPORT CWriteEngine2Event::XWriteEngine2Events::AddRef()
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CWriteEngine2Event::XWriteEngine2Events::Release()
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	return pThis->ExternalRelease();
}
STDMETHODIMP CWriteEngine2Event::XWriteEngine2Events::QueryInterface(REFIID riid,
												   LPVOID FAR* ppvObj)
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	return (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
}
STDMETHODIMP
CWriteEngine2Event::XWriteEngine2Events::GetTypeInfoCount(UINT FAR* pctinfo)
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	*pctinfo = 1;
	return NOERROR;
}
STDMETHODIMP CWriteEngine2Event::XWriteEngine2Events::GetTypeInfo(
	UINT itinfo,
	LCID lcid,
	ITypeInfo FAR* FAR* pptinfo)
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	*pptinfo = NULL;

	if(itinfo != 0)
		return ResultFromScode(DISP_E_BADINDEX);
	pThis->m_ptinfo->AddRef();
	*pptinfo = pThis->m_ptinfo;
	return NOERROR;
}
STDMETHODIMP CWriteEngine2Event::XWriteEngine2Events::GetIDsOfNames(
	REFIID riid,
	OLECHAR FAR* FAR* rgszNames,
	UINT cNames,
	LCID lcid,
	DISPID FAR* rgdispid)
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	return DispGetIDsOfNames(pThis->m_ptinfo, rgszNames, cNames, rgdispid);
}

STDMETHODIMP CWriteEngine2Event::XWriteEngine2Events::Invoke(
	DISPID dispidMember,
	REFIID riid,
	LCID lcid,
	WORD wFlags,
	DISPPARAMS FAR* pdispparams,
	VARIANT FAR* pvarResult,
	EXCEPINFO FAR* pexcepinfo,
	UINT FAR* puArgErr)
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)

	return DispInvoke(&pThis->m_xWriteEngine2Events, pThis->m_ptinfo,
		dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}

//
///////////////////////////////////////////////////////////////////////
//
// CWriteEngine2Event::CreateEventSink
//
// Description:
//			Establishes a link between the CWriteEngine2(IDiscFormat2Erase)
//			and the CWriteEngine2Event(DWriteEngine2Events) so 
//			CWriteEngine2Event can receive Update messages
//
CWriteEngine2Event* CWriteEngine2Event::CreateEventSink()
{
	// Create the event sink
	CWriteEngine2Event* pWriteEngine2Event = new CWriteEngine2Event();

	pWriteEngine2Event->EnableAutomation();
	pWriteEngine2Event->ExternalAddRef();

	return pWriteEngine2Event;
}

///////////////////////////////////////////////////////////////////////
//
// CWriteEngine2Event::ConnectWriteEngine2
//
// Description:
//			Establishes a connection between the CWriteEngine2(IDiscFormat2Erase)
//			and the CWriteEngine2Event(DWriteEngine2Events) so 
//			CWriteEngine2Event can receive Update messages
//
bool CWriteEngine2Event::ConnectWriteEngine2(CWriteEngine2* pWriteEngine2)
{
	m_pUnkSink = GetIDispatch(FALSE);
	m_pUnkSrc = pWriteEngine2->GetInterface();

	LPTYPELIB ptlib = NULL;
	HRESULT hr = LoadRegTypeLib(LIBID_IMAPILib2, IMAPILib2_MajorVersion, IMAPILib2_MinorVersion, LOCALE_SYSTEM_DEFAULT, &ptlib);
	if (FAILED(hr))
	{
		return false;
	}
	hr = ptlib->GetTypeInfoOfGuid(IID_DWriteEngine2Events, &m_ptinfo);
    ptlib->Release();
	if (FAILED(hr))
	{
	    return false;
	}

	BOOL bRet = AfxConnectionAdvise(m_pUnkSrc, IID_DWriteEngine2Events, m_pUnkSink,
		TRUE, &m_dwCookie);
	if (bRet)
	{
		return true;
	}

	return false;
}

///////////////////////////////////////////////////////////////////////
//
// CWriteEngine2Event::Update
//
// Description:
//			Receives update notifications from IDiscFormat2Erase
//
STDMETHODIMP_(HRESULT) CWriteEngine2Event::XWriteEngine2Events::Update(IDispatch* objectDispatch, IDispatch* progressDispatch)
{
	METHOD_PROLOGUE(CWriteEngine2Event, WriteEngine2Events)
	HRESULT hr = S_OK;

	IWriteEngine2EventArgs* progress = NULL;
	hr = progressDispatch->QueryInterface(IID_PPV_ARGS(&progress));

	IDiscFormat2Erase* WriteEngine2 = NULL;
    hr = objectDispatch->QueryInterface(IID_PPV_ARGS(&WriteEngine2));

    IMAPI_STATUS imapiStatus = {0};
	
	progress->get_StartLba(&imapiStatus.startLba);
	progress->get_SectorCount(&imapiStatus.sectorCount);
	progress->get_LastReadLba(&imapiStatus.lastReadLba);
	progress->get_LastWrittenLba(&imapiStatus.lastWrittenLba);
	progress->get_TotalSystemBuffer(&imapiStatus.totalSystemBuffer);
	progress->get_UsedSystemBuffer(&imapiStatus.usedSystemBuffer);
	progress->get_FreeSystemBuffer(&imapiStatus.freeSystemBuffer);

	LRESULT ret = ::SendMessage(pThis->m_hNotifyWnd, WM_IMAPI_UPDATE, IMAPI_WRITE_ENGINE2_ACTION_WRITING_MEDIA, (LPARAM)(LPVOID)&imapiStatus);
	return S_OK;
}

